﻿/*************************************************
网络(读/写) 线程管理
author：Daixiwei
**************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;

namespace taurus.client
{
    /// <summary>
    /// 网络(读/写) 线程管理
    /// </summary>
    public class ThreadManager
    {
        class MessgaeThread
        {
            public Action<Message> _dataDelegate;

            public Message _message;
        }

        private Stack<MessgaeThread> pool = new Stack<MessgaeThread>();
        private MessgaeThread MessgaeThreadGet()
        {
            if (pool.Count > 0)
            {
                MessgaeThread msg = pool.Pop();
                return msg;
            }
            else
                return new MessgaeThread();
        }

        private void MessgaeThreadReturn(MessgaeThread value)
        {

            pool.Push(value);
            value._dataDelegate = null;
            value._message = null;
        }


        private bool _running = false;

        private Thread _outThread;

        private bool _outHasQueuedItems = false;

        private Queue<MessgaeThread> _outThreadQueue = new Queue<MessgaeThread>();

        private object _outQueueLocker = new object();

        private static void Sleep(int ms)
        {
            Thread.Sleep(ms);
        }


        private void OutThread()
        {
            while (_running)
            {
                Sleep(5);
                if (_outHasQueuedItems)
                {
                    object obj = _outQueueLocker;
                    lock (obj)
                    {
                        while (_outThreadQueue.Count > 0)
                        {
                            var item = _outThreadQueue.Dequeue();
                            ProcessOutItem(item);
                        }
                        _outHasQueuedItems = false;
                    }
                }
            }
        }

        

        private void ProcessOutItem(MessgaeThread item)
        {
            Action<Message> _dataDelegate = item._dataDelegate;
            var message = item._message;
            MessgaeThreadReturn(item);
            if (_dataDelegate != null)
            {
                _dataDelegate(message);
            }
        }

        public void start()
        {
            if (_running)
            {
                return;
            }
            _running = true;
            if (_outThread == null)
            {
                _outThread = new Thread(new ThreadStart(OutThread));
                _outThread.IsBackground = true;
                _outThread.Start();
            }
        }

        public void stop()
        {
            Thread thread = new Thread(new ThreadStart(stopThread));
            thread.IsBackground = true;
            thread.Start();
        }

        private void stopThread()
        {
            _running = false;
            
            if (_outThread != null)
            {
                _outThread.Join();
            }
            _outThread = null;
        }

        public void enqueueSend(Action<Message> callback,Message message)
        {
            var hashtable = MessgaeThreadGet();
            hashtable._dataDelegate = callback;
            hashtable._message = message;
            object obj = _outQueueLocker;
            lock (obj)
            {
                _outThreadQueue.Enqueue(hashtable);
                _outHasQueuedItems = true;
            }
        }
    }
}